#include "../include/EventLoop.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <iostream>
#include <sys/eventfd.h>
using std::endl;
using std::cout;
using std::pair;
EventLoop::EventLoop(Acceptor & acceptor)
    :_epfd(createEpollFd())
    ,_eventfd(createEventFd())
    ,_eventList(100)
    ,_islooping(false)
    ,_acceptor(acceptor)
{
    AddEpollFd(_acceptor.fd());
    AddEpollFd(_eventfd);
}

EventLoop::~EventLoop()
{
    close(_eventfd);
    close(_epfd);
}

void EventLoop::loop()
{
        _islooping = true;
        //进行事件循环
        while(_islooping){
            waitEpollFd();
        }
}
void EventLoop::unloop()
{
    _islooping = false;
}
void EventLoop::waitEpollFd()
{
    
    //阻塞,vector的data函数返回的是动态数组的首元素地地址
    int nready = epoll_wait(_epfd, _eventList.data(),_eventList.size(), -1);
    if(nready == -1 && errno == EINTR)
    {
        return;
    }
    else if(nready == -1)
    {
        perror("epoll_wait");
        return;
    }
    else if(nready == 0)
    {
        cout << "epoll time out" << endl;
    }
    else
    {
        //遍历vector处理所有的就绪文件描述符
        for(int i = 0; i < nready; ++i)
        {
            int fd = _eventList[i].data.fd;
            if(fd == _acceptor.fd())
            {
                //说明是新的连接
                handleNewConnection();
            }
            else if(fd == _eventfd)
            {
                // cout << "EventLoop.cpp, 74, fd = " << fd << endl;
                handleRead();
                doPendingFunctors();
            }
            else
            {
                //说明是新的数据发送过来
                handleMessage(fd);

            }
        }

    }


}
int EventLoop::createEpollFd()
{
    int epfd;
    if((epfd = epoll_create1(0)) < 0)
    {
        perror("epoll_create");
    }
    // cout << "EventLoop.cpp 95 createEpollFd()  _epfd = " << epfd << endl;
    return epfd;
}
void EventLoop::AddEpollFd(int fd)
{
    struct epoll_event event;
    memset(&event, 0, sizeof(event));
    event.data.fd = fd;
    event.events = EPOLLIN;
    int ret = epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &event);
    if(ret < 0)
    {
        perror("epoll_ctli add");
    }
}
void EventLoop::DelEpollFd(int fd)
{
    struct epoll_event event;
    memset(&event, 0, sizeof(event));
    event.data.fd = fd;
    int ret = epoll_ctl(_epfd, EPOLL_CTL_DEL,fd, &event);
    if(ret < 0)
    {
        perror("epoll_ctl delete");
    }

}
void EventLoop::handleNewConnection()
{
    //accept
    int connfd = _acceptor.accept();
    if(connfd < 0)
    {
        perror("accept");
    }
    //将新的fd添加到epoll
    AddEpollFd(connfd);
    //创建新的TcpConnection对象
    TcpConnectionPtr sp(new TcpConnection(connfd, this));
    _conns.insert(make_pair(connfd, sp));
    sp->setAllCallbacks(_onClose, _onMessage, _onConnection);
    sp->handleConnectionCallback();

}
void EventLoop::handleMessage(int fd)
{
    //先将对应的TcpConnection找到
    auto it = _conns.find(fd);
    if(it != _conns.end())
    {
        //找到了
       if(it->second->isClosed())
       {
           it->second->handleCloseCallback();
           DelEpollFd(fd);
           _conns.erase(fd);
       }
       else
       {
            it->second->handleMessageCallback();
            // cout << "EventLoop.cpp 159 handleMessage(), after handle messageCallback" << endl;
       }
        
    }

}
void EventLoop::setAllCallbacks(Callback &&Close, Callback &&Msg, Callback &&On)
{
    _onClose = std::move(Close);
    _onMessage = std::move(Msg);
    _onConnection = std::move(On);
}


int EventLoop::createEventFd()
{
    int fd = eventfd(0,0);
    if(fd < 0)
    {
        perror("eventfd");
    }
    return fd;

}

//这个函数是计算线程在执行Task中的process函数后，在处理完msg后调用，将TcpConnection
//通过sendtoloop函数将send传到EventLoop对象中执行
void EventLoop::runInLoop(Functor && cb)
{
    _mux.lock();
    _pendingFunctors.push_back(cb);
    _mux.unlock();


    //通知io线程要执行send函数，发送数据了
    wakeup();
}

//该函数在runinloop中被调用
void EventLoop::wakeup()
{
    uint64_t one;
    //在这里激活eventfd，并且执行handleread和dopendingfunctor函数
    int ret = write(_eventfd, &one,sizeof(one));
    if(ret < 0)
    {
        perror("write eventfd");
    }
}
//消费事件，不然eventfd下一次将不会被触发
void EventLoop::handleRead()
{
    uint64_t one = 0;
    int ret = read(_eventfd, &one,sizeof(one));
    if(ret < 0)
    {
        perror("read eventfd");
    }
}
//这里是io线程执行，执行被传递过来的send函数
void EventLoop::doPendingFunctors()
{
    vector<Functor> temp;
    _mux.lock();
    temp.swap(_pendingFunctors);
    _mux.unlock();
    for(auto & a : temp)
    {
        //这里的a实际上是TcpConnection函数内的send函数
        a();

    }


    
}
